﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Text.RegularExpressions;
using System.Reflection;
using System.Data.OleDb;
using AliCMS.SystemModule;

namespace AliCMS.TemplateEngine
{
    internal class List : Tag
    {
        internal List(Engine engine, int index, int length, int contentIndex, int contentLength, Tag parent)
            : base(engine, index, length, contentIndex, contentLength, parent)
        {
        }

        internal override void Init()
        {
            #region 获取Row,Col和Record
            foreach (Tag tag in ChildTags)
            {
                if (tag is Row)
                {
                    _row = tag;
                    break;
                }

                if (tag is Col)
                {
                    _col = tag;
                    break;
                }

                if (tag is Record)
                {
                    _record = tag;
                    break;
                }
            }

            if (_row != null || _col != null)
            {
                if (_row != null && _col == null)
                {
                    if (_row.ChildTags[0] is Col)
                    {
                        _col = _row.ChildTags[0];
                    }
                    else if (_row.ChildTags[0] is Record)
                    {
                        _record = _row.ChildTags[0];
                    }
                    else if (!(_row.ChildTags[0] is Separator))
                    {
                        Exception exp = new Exception("lang_parse_template_row_just_include_col_record");
                        Engine.ReportError(exp, _row.Index);
                    }
                }

                if (_record == null)
                {
                    if (_col.ChildTags[0] is Record)
                    {
                        _record = _col.ChildTags[0];
                    }
                    else if (!(_col.ChildTags[0] is Separator))
                    {
                        Exception exp = new Exception("lang_parse_template_col_just_include_record");
                        Engine.ReportError(exp, _col.Index);
                    }
                }
            }
            #endregion

            Regex re = null;
            Match match = null;

            #region Mark
            _mark = String.Empty;
            re = new Regex("Mark=\"(?<v>.*?)\"", RegexOptions.Compiled);
            if (_record == null)
                match = re.Match(Engine.Text, Index, Length);
            else
                match = re.Match(Engine.Text, Index, ContentIndex - Index);
            if (match.Success)
                _mark = match.Groups["v"].Value;
            #endregion

            #region Module
            _module = Engine.GetModuleByMark(_mark);
            #endregion

            #region Instance
            _instance = String.Empty;
            re = new Regex("Instance=\"(?<v>.*?)\"", RegexOptions.Compiled);
            if (_record == null)
                match = re.Match(Engine.Text, Index, Length);
            else
                match = re.Match(Engine.Text, Index, ContentIndex - Index);
            if (match.Success)
                _instance = match.Groups["v"].Value;
            #endregion

            #region Object
            re = new Regex("Object=\"(?<v>.*?)\"", RegexOptions.Compiled);
            if (_record == null)
                match = re.Match(Engine.Text, Index, Length);
            else
                match = re.Match(Engine.Text, Index, ContentIndex - Index);
            if (match.Success)
            {
                string objectName = match.Groups["v"].Value;

                DataRow[] rows = null;
                if (_module != null)
                    rows = Manager.Objects.Select(Alias.Module.Object.Namespace + "='" + _module[Alias.Module.Namespace] + "' and FullName='" + objectName + "'");
                if (rows == null || rows.Length == 0)
                {
                    Exception exp = new Exception("lang_parse_template_module_not_include_object");
                    exp.Data.Add(3, _module[Alias.Module.Name]);
                    exp.Data.Add(4, objectName);
                    Engine.ReportError(exp, Index);
                }

                _object = rows[0];

                #region InterfaceName
                _interfaceName = String.Empty;
                int dot = objectName.LastIndexOf('.');
                if (dot != -1)
                    _interfaceName = objectName.Insert(dot + 1, "I");
                else
                    _interfaceName = "I" + objectName;
                #endregion
            }
            #endregion

            #region id
            _id = Id;
            if (String.IsNullOrEmpty(_id))
                _id = UniqueName + "ID";
            #endregion

            #region Operation
            _operationName = "List";
            re = new Regex("Operation=\"(?<v>.*?)\"", RegexOptions.Compiled);
            if (_record == null)
                match = re.Match(Engine.Text, Index, Length);
            else
                match = re.Match(Engine.Text, Index, ContentIndex - Index);
            if (match.Success)
            {
                //带圆括号表示有参数，否则认为List函数的变异
                if (match.Groups["v"].Value.Contains("("))
                {
                    _operation = Engine.CreateExpression(this, match.Groups["v"].Value);
                    string functionName = _operation.Value;
                    int paramaterCount = 1;
                    if (_operation.Type == ExpressionType.Function)
                    {
                        functionName = _operation.FunctionName;
                        paramaterCount = _operation.Params.Count;
                    }

                    string typeName = _module[Alias.Module.Namespace] + "." + _interfaceName;
                    Type type = Type.GetType(typeName);
                    if (type == null)
                    {
                        Assembly assembly = null;
                        //if (String.Equals(_module[Alias.Module.Namespace], "AliCMS.SystemModule"))
                        //    assembly = Assembly.Load("AliCMS.Base");
                        //else
                            assembly = Assembly.Load(_module[Alias.Module.Namespace] + ".Interface");
                        type = assembly.GetType(typeName);
                    }

                    MethodInfo mi = null;
                    MethodInfo[] mis = type.GetMethods();
                    for (int i = 0; i < mis.Length; i++)
                    {
                        if (mis[i].Name == functionName && mis[i].GetParameters().Length == paramaterCount)
                        {
                            mi = mis[i];
                            break;
                        }
                    }

                    if (mi == null)
                    {
                        Type[] types = type.GetInterfaces();
                        foreach (Type t in types)
                        {
                            mi = t.GetMethod(functionName);
                            if (mi != null)
                                break;
                        }

                        if (mi == null)
                        {
                            Exception exp = new Exception("lang_parse_template_object_not_include_operation");
                            exp.Data.Add(3, _object["FullName"]);
                            exp.Data.Add(4, functionName);
                            Engine.ReportError(exp, match.Groups["v"].Index);
                        }
                    }

                    _returnType = mi.ReturnType;
                    if (_returnType.Name != "DataTable")
                    {
                        Exception exp = new Exception("lang_parse_template_return_value_must_datatable");
                        exp.Data.Add(3, functionName);
                        Engine.ReportError(exp, match.Groups["v"].Index);
                    }

                    _pi = mi.GetParameters();
                    if (paramaterCount != _pi.Length)
                    {
                        Exception exp = new Exception("lang_parse_template_params_count_not_correct");
                        exp.Data.Add(3, functionName);
                        Engine.ReportError(exp, match.Groups["v"].Index);
                    }
                }
                else
                {
                    _operationName = match.Groups["v"].Value;
                }
            }
            #endregion

            #region Source
            re = new Regex("Source=\"(?<v>.*?)\"", RegexOptions.Compiled);
            if (_record == null)
                match = re.Match(Engine.Text, Index, Length);
            else
                match = re.Match(Engine.Text, Index, ContentIndex - Index);
            if (match.Success)
            {
                _source = Engine.CreateExpression(this, match.Groups["v"].Value);
            }
            #endregion

            #region Lang
            re = new Regex("Lang=\"(?<v>.*?)\"", RegexOptions.Compiled);
            if (_record == null)
                match = re.Match(Engine.Text, Index, Length);
            else
                match = re.Match(Engine.Text, Index, ContentIndex - Index);
            if (match.Success)
            {
                _lang = match.Groups["v"].Value;
            }
            #endregion

            #region 需要处理的子标签输出表达式
            if (_record != null)
            {
                _aliasStatment = new StringBuilder();
                _statment = new StringBuilder();
                _complex = new StringBuilder();
                _repeatCheckList = new List<string>();
                InitAliasStatment(_record.ChildTags);
            }
            #endregion
        }
        internal override void Parse()
        {
            ParseToCode();
            ParseToXml();
        }
        internal override string ParseVariable(Expression variable)
        {
            if (variable.Parent != null && variable.Parent.Right == variable && variable.Parent.Operator == ".")
                return null;

            if (variable.Value.StartsWith("[") && variable.Value.EndsWith("]"))
                return _id + ".Rows[" + _id + "Counter]" + variable.Value;

            StringBuilder result = null;
            MatchCollection matches = Regex.Matches(variable.Value, @"((?<id>[a-zA-Z_]\w*)\[(?<counter>\d+)\]\[(?<name>[a-zA-Z_]\w*)\])|((?<id>[a-zA-Z_]\w*)\[(?<name>[a-zA-Z_]\w*)\])|((?<id>[a-zA-Z_]\w*)\[(?<name>""[a-zA-Z_]\w*"")\])|([a-zA-Z_]\w*)");
            for (int i = matches.Count - 1; i >= 0; i--)
            {
                Match match = matches[i];

                string value = String.Empty;
                if (match.Groups["id"].Success)
                {
                    if (match.Groups["id"].Value != Id)
                        continue;

                    value = match.Groups["name"].Value;
                }
                else
                {
                    value = match.Value;
                }

                DataRow[] rows = null;
                if (_object != null && (match.Groups["id"].Success || _record != null))
                    rows = Manager.Properties.Select(Alias.Module.Object.Property.ObjectID + "='" + _object[Alias.Module.Object.ID] + "' and " + Alias.Module.Object.Property.Name + "='" + value + "'");
                if (rows == null || rows.Length == 0)
                {
                    if (value != "Index" && value != "Count" && value != "RecordCount" && value != "Record" && !(value.StartsWith("\"") && value.EndsWith("\"")))
                        continue;

                    if (result == null)
                        result = new StringBuilder(variable.Value);

                    if (value == "Index")
                    {
                        result.Remove(match.Index, match.Length);
                        result.Insert(match.Index, _id + "Counter");
                    }
                    else if (value == "Count")
                    {
                        result.Remove(match.Index, match.Length);
                        result.Insert(match.Index, _id + ".Rows.Count");
                    }
                    else if (value == "RecordCount")
                    {
                        result.Remove(match.Index, match.Length);
                        result.Insert(match.Index, _id + "RecordCount");
                    }
                    else if (value == "Record")
                    {
                        result.Remove(match.Index, match.Length);
                        result.Insert(match.Index, "(" + _id + "Record as System.Data.DataRow)");
                    }
                    else if (value.StartsWith("\"") && value.EndsWith("\""))
                    {
                        result.Remove(match.Index, match.Length);
                        result.Insert(match.Index, _id + ".Rows[" + _id + "Counter][" + value + "]");
                    }
                }
                else
                {
                    bool doit = match.Groups["id"].Success;
                    if (!doit)
                    {
                        object source = variable.Source;
                        while (!(source is Tag))
                        {
                            source = ((Expression)source).Source;
                        }
                        Tag tag = source as Tag;

                        doit = tag.Index >= _record.Index && tag.Index + tag.Length <= _record.Index + _record.Length;
                    }

                    if (doit)
                    {
                        if (result == null)
                            result = new StringBuilder(variable.Value);

                        result.Remove(match.Index, match.Length);
                        string alias = _module[Alias.Module.Namespace] + ".Alias." + _object["FullName"] + "." + value;
                        if (match.Groups["counter"].Success)
                            result.Insert(match.Index, _id + ".Rows[" + match.Groups["counter"].Value + "][" + alias + "]");
                        else
                            result.Insert(match.Index, _id + ".Rows[" + _id + "Counter][" + alias + "]");
                    }
                }
            }

            return result == null ? null : result.ToString();
        }
        internal override string ParseFunction(Expression function)
        {
            if (function.FunctionName != "BuildUrl" || function.Params.Count > 1 || _object == null)
                return null;

            #region 如果带一个参数并且不是Record的里面的，则返回
            if (function.Params.Count == 1)
            {
                bool isRecord = false;
                Tag parent = function.Source as Tag;
                while (parent != null)
                {
                    if (parent is Record)
                    {
                        isRecord = true;
                        break;
                    }

                    parent = parent.Parent;
                }

                if (!isRecord)
                    return null;
            }
            #endregion

            if (String.IsNullOrEmpty(_mark) || !String.IsNullOrEmpty(_instance))
                function.InsertParam(0, Engine.IsMultiSite ? "SubChannel" : "Channel", true);
            else
                function.InsertParam(0, Engine.ParseChannel(_mark), true);

            #region 判断和获取pageTemplate, pageID, pageExtension, PageUrl
            string objectName = _object["FullName"].ToString();
            string pageTemplate = null;
            string pageID = null;
            string pageUrl = null;
            string innerID = null;
            DataRow[] properties = Manager.Properties.Select(Alias.Module.Object.Property.ObjectID + "='" + _object[Alias.Module.Object.ID] + "'");
            foreach (DataRow property in properties)
            {
                string name = property[Alias.Module.Object.Property.Name].ToString();
                string id = property[Alias.Module.Object.Property.UniqueInnerID].ToString();

                if (name == "PageTemplate")
                    pageTemplate = id;
                else if (name == "PageID")
                    pageID = id;
                else if (name == "PageUrl")
                    pageUrl = id;
                else if (name == "InnerID")
                    innerID = id;
            }

            #region 处理交叉表情况
            if (pageID == null && objectName.IndexOf('.') != -1)
            {
                string prefix = objectName.Substring(objectName.LastIndexOf('.') + 1);

                foreach (DataRow property in properties)
                {
                    string name = property[Alias.Module.Object.Property.Name].ToString();
                    string id = property[Alias.Module.Object.Property.UniqueInnerID].ToString();

                    if (name == prefix + "PageTemplate")
                        pageTemplate = id;
                    else if (name == prefix + "PageID")
                        pageID = id;
                    else if (name == prefix + "PageUrl")
                        pageUrl = id;
                }
            }
            #endregion
            #endregion

            #region PathInTemplate
            if (function.Params.Count == 1)
            {
                string pathInTemplate = null;
                for (int i = 0; i < objectName.Length; i++)
                {
                    if (objectName[i] == '.')
                    {
                        pathInTemplate += "/";
                    }
                    else
                    {
                        if (i > 0 && Char.IsUpper(objectName[i]) && objectName[i - 1] != '.')
                            pathInTemplate += "_";
                        pathInTemplate += Char.ToLower(objectName[i]);
                    }
                }

                pathInTemplate = "\"" + pathInTemplate + "\"";
                function.InsertParam(-1, pathInTemplate, true);
            }
            #endregion

            #region Header
            string header = null;

            if (String.IsNullOrEmpty(pageID) && !String.IsNullOrEmpty(innerID))
                header = "\"ID=\" + " + _id + ".Rows[" + _id + "Counter][\"" + innerID + "\"]";
            else if (!String.IsNullOrEmpty(pageID))
                header = "\"ID=\" + " + _id + ".Rows[" + _id + "Counter][\"" + pageID + "\"]";
            else
                header = "\"\"";

            if (!String.IsNullOrEmpty(pageTemplate))
                header += " + \"&PageTemplate=\" + " + _id + ".Rows[" + _id + "Counter][\"" + pageTemplate + "\"]";

            if (!String.IsNullOrEmpty(pageUrl))
                header += " + \"&PageUrl=\" + HttpUtility.UrlEncode(" + _id + ".Rows[" + _id + "Counter][\"" + pageUrl + "\"].ToString())";

            function.InsertParam(-1, header, true);
            #endregion

            return function.FunctionName;
        }

        private void InitAliasStatment(List<Tag> childTags)
        {
            foreach (Tag tag in childTags)
            {
                if (tag is List || tag is Tree || tag is Get)
                    continue;

                if (!(tag is OutputStatment))
                {
                    InitAliasStatment(tag.ChildTags);
                    continue;
                }

                OutputStatment osTag = tag as OutputStatment;

                string content = Engine.Text.Substring(osTag.ContentIndex, osTag.ContentLength);
                if (content == "Index")
                {
                    osTag.IsAliasStatment = true;
                    osTag.AliasXml = content;
                    osTag.AliasCode = "null";

                    if (_repeatCheckList.Contains(content))
                        continue;

                    _aliasStatment.Append("replacementPair[\"{#" + osTag.AliasXml + "#}\"] = " + osTag.AliasCode + ";");
                }
                else if (content.StartsWith("[") && content.EndsWith("]"))
                {
                    osTag.IsAliasStatment = true;
                    osTag.AliasXml = content;
                    osTag.AliasCode = content.Substring(1, content.Length - 2);

                    if (_repeatCheckList.Contains(content))
                        continue;

                    _aliasStatment.Append("replacementPair[\"{#" + osTag.AliasXml.Replace("\"", "\\\"") + "#}\"] = " + osTag.AliasCode + ";");
                }
                else if (_object != null && Manager.Properties.Select(Alias.Module.Object.Property.ObjectID + "='" + _object[Alias.Module.Object.ID] + "' and " + Alias.Module.Object.Property.Name + "='" + content + "'").Length == 1)
                {
                    osTag.IsAliasStatment = true;
                    osTag.AliasXml = content;
                    osTag.AliasCode = _module[Alias.Module.Namespace] + ".Alias." + _object["FullName"] + "." + content;

                    if (_repeatCheckList.Contains(content))
                        continue;

                    _aliasStatment.Append("replacementPair[\"{#" + osTag.AliasXml + "#}\"] = " + osTag.AliasCode + ";");
                }

                if (osTag.IsAliasStatment)
                    _repeatCheckList.Add(content);
            }
        }
        private StringBuilder ParseCondition()
        {
            StringBuilder result = new StringBuilder();
            result.Append("string condition = null;\r\n");
            Regex re = new Regex("Condition=\"(?<v>.*?)\"", RegexOptions.Compiled);
            Match match = null;
            if (_record == null)
                match = re.Match(Engine.Text, Index, Length);
            else
                match = re.Match(Engine.Text, Index, ContentIndex - Index);
            if (match.Success)
            {
                DataRow[] properties = Manager.Properties.Select(Alias.Module.Object.Property.ObjectID + "='" + _object[Alias.Module.Object.ID] + "'");

                #region 排序
                DataTable propertyTable = new DataTable();
                propertyTable.Columns.Add("Name", typeof(string));
                propertyTable.Columns.Add("Alias", typeof(string));
                propertyTable.Columns.Add("OleDbType", typeof(byte));
                propertyTable.Columns.Add("Width", typeof(int));

                foreach (DataRow property in properties)
                {
                    DataRow newRow = propertyTable.NewRow();
                    newRow["Name"] = property[Alias.Module.Object.Property.Name];
                    newRow["Alias"] = property[Alias.Module.Object.Property.UniqueInnerID];
                    newRow["OleDbType"] = property[Alias.Module.Object.Property.OleDbType];
                    newRow["Width"] = newRow["Name"].ToString().Length;
                    propertyTable.Rows.Add(newRow);
                }

                properties = propertyTable.Select("", "Width DESC");
                #endregion

                #region 获取类型
                Dictionary<int, OleDbType> types = new Dictionary<int, OleDbType>();
                MatchCollection matches = Regex.Matches(match.Groups["v"].Value, @"(?<n>[a-zA-Z_]\w*)\s?(=|>|<|<>|>=|<=)\s?(?<v>[a-zA-Z_]\w*\[[a-zA-Z_]\w*\])");
                foreach (Match m in matches)
                {
                    DataRow[] rows = propertyTable.Select("Name='" + m.Groups["n"].Value + "'");
                    if (rows.Length == 0 || Convert.IsDBNull(rows[0]["OleDbType"]))
                        continue;

                    types.Add(m.Groups["v"].Index, (OleDbType)(byte)rows[0]["OleDbType"]);
                }
                #endregion

                bool hasLastParenthis = false;
                int start = 0;
                int end = 0;
                matches = Regex.Matches(match.Groups["v"].Value, @"(\)?\s+(and|or)\s+(\(\s?)?)?(?<n>\w+)\s*(>=|<=|<>|=|>|<|\sLIKE\s|\sIS NOT\s|\sIS\s)\s*", RegexOptions.Compiled | RegexOptions.IgnoreCase);
                for (int i = 0; i < matches.Count; i++)
                {
                    Group nameGroup = matches[i].Groups["n"];
                    string name = nameGroup.Value;
                    string alias = name;
                    foreach (DataRow property in properties)
                    {
                        if (property["Name"].ToString() == name)
                        {
                            alias = property["Alias"].ToString();
                            break;
                        }
                    }

                    string temp = matches[i].Value.Remove(nameGroup.Index - matches[i].Index, nameGroup.Length);
                    temp = temp.Insert(nameGroup.Index - matches[i].Index, alias);
                    result.Append("condition += \"" + temp + "\";\r\n");

                    start = matches[i].Index + matches[i].Length;
                    if (i < matches.Count - 1)
                        end = matches[i + 1].Index;
                    else
                        end = match.Groups["v"].Value.Length;
                    string value = match.Groups["v"].Value.Substring(start, end - start);

                    if (i == matches.Count - 1 && value.EndsWith(")"))
                    {
                        value = value.Remove(value.Length - 1);
                        hasLastParenthis = true;
                    }

                    #region 已知常量
                    if (Regex.IsMatch(value, @"^(false|true|NULL|\d+|\{?[a-fA-F0-9]{8}(-?[a-fA-F0-9]{4}){3}-?[a-fA-F0-9]{12}\}?|'[^']*')$", RegexOptions.Compiled | RegexOptions.IgnoreCase))
                    {
                        result.Append("condition += \"" + value + "\";\r\n");
                        continue;
                    }
                    #endregion

                    DataRow[] rows = propertyTable.Select("Name='" + name + "'");
                    if (rows.Length == 0 || Convert.IsDBNull(rows[0]["OleDbType"]))
                    {
                        result.Append("condition += " + Engine.ParseExpression(this.Parent == null ? this : this.Parent, value) + ";\r\n");
                    }
                    else
                    {
                        OleDbType type = (OleDbType)(byte)rows[0]["OleDbType"];
                        if (type == OleDbType.Guid)
                        {
                            result.Append("object v" + i + " = " + Engine.ParseExpression(this.Parent == null ? this : this.Parent, value) + ";");
                            if (_source == null)
                            {
                                result.Append(@"
                                            if (v" + i + @" == null)
                                                condition = condition.Substring(0, condition.Length - " + (temp.StartsWith(")") ? temp.Length - 1 : temp.Length) + @");
                                            else if (v" + i + @".ToString() == String.Empty)
                                                condition = condition.Substring(0, condition.Length - 1) + "" IS NULL "";
                                            else
                                                condition += v" + i + @".ToString();
                                            ");
                            }
                            else
                            {
                                result.Append(@"
                                            if (v" + i + @" == null)
                                                condition = condition.Substring(0, condition.Length - " + (temp.StartsWith(")") ? temp.Length - 1 : temp.Length) + @");
                                            else if (v" + i + @".ToString() == String.Empty)
                                                condition = condition.Substring(0, condition.Length - 1) + "" IS NULL "";
                                            else
                                                condition += ""'"" + v" + i + @" + ""'"";
                                            ");
                            }
                        }
                        else if (type == OleDbType.BSTR || type == OleDbType.Char || type == OleDbType.LongVarChar || type == OleDbType.LongVarWChar || type == OleDbType.VarChar || type == OleDbType.VarWChar || type == OleDbType.WChar)
                        {
							string v = Engine.ParseExpression(this.Parent == null ? this : this.Parent, value);
							result.Append("condition += \"'\" + (" + v + "==null?\"\":" + v + ".ToString().Replace(\"'\", \"''\")) + \"'\";\r\n");
                        }
                        else if (type == OleDbType.Date || type == OleDbType.DBDate || type == OleDbType.DBTime || type == OleDbType.DBTimeStamp)
                        {
                            result.Append("condition += \"#\" + Convert.ToDateTime(" + Engine.ParseExpression(this.Parent == null ? this : this.Parent, value) + ").ToString(\"yyyy-MM-dd HH:mm:ss\") + \"#\";\r\n");
                        }
                        else
                        {
                            result.Append("condition += " + Engine.ParseExpression(this.Parent == null ? this : this.Parent, value) + ";\r\n");
                        }
                    }
                }

                if (matches.Count == 0)
                    result.Append("condition += " + Engine.ParseExpression(this.Parent == null ? this : this.Parent, match.Groups["v"].Value) + ";\r\n");

                if (hasLastParenthis)
                    result.Append("condition += \")\";");
            }

            #region 如果是站群并且没指定Instance属性，并且当前对象包含SubInstanceID，则限制SubInstanceID
            if (Engine.IsMultiSite && String.IsNullOrEmpty(_instance))
            {
                DataRow[] rows = Manager.Properties.Select(Alias.Module.Object.Property.ObjectID + "='" + _object[Alias.Module.Object.ID] + "' AND " + Alias.Module.Object.Property.Name + "='SubInstanceID'");
                if (rows.Length > 0)
                {
                    result.Append(@"
                                if (condition == null || !condition.Contains(""" + rows[0][Alias.Module.Object.Property.UniqueInnerID] + @"""))
                                {
                                    if (!String.IsNullOrEmpty(condition))
                                        condition += "" AND "";
                                    condition += """ + rows[0][Alias.Module.Object.Property.UniqueInnerID] + @"='"" + GetBindingSubInstanceID(" + Engine.ParseChannel(_mark) + @") + ""'"";
                                }
                                ");
                }
            }
            #endregion

            return result;
        }
        private void ParseToCode()
        {
            StringBuilder result = new StringBuilder();
            Regex re = null;
            Match match = null;

            #region InstanceID
            string instanceID = "int instanceID;\r\n";
            if (String.IsNullOrEmpty(_mark))
            {
                if (Engine.IsMultiSite)
					instanceID += "instanceID = SubInstanceID;";
				else
					instanceID += "instanceID = InstanceID;";
			}
            else
            {
                if (String.IsNullOrEmpty(_instance))
                {
                    if (Engine.IsMultiSite)
						instanceID += "instanceID = (int)Manager.Instances.Select(AliCMS.SystemModule.Alias.Instance.ID + \"='\" + GetBindingInstanceID(" + Engine.ParseChannel(_mark) + ") + \"'\")[0][AliCMS.SystemModule.Alias.Instance.InnerID];";
                    else
                        instanceID += "instanceID = (int)" + Engine.ParseChannel(_mark) + "[AliCMS.SystemModule.Alias.Instance.InnerID];";
                }
                else
                {
                    if (Regex.IsMatch(_instance, @"\{?[a-fA-F0-9]{8}(-?[a-fA-F0-9]{4}){3}-?[a-fA-F0-9]{12}\}?"))
                    {
						instanceID += "instanceID = " + Manager.Instances.Select(Alias.Instance.ID + "='" + _instance + "'")[0][Alias.Instance.InnerID] + ";";
                    }
                    else
                    {
                        instanceID += "string instanceIDTemp = Convert.ToString(" + Engine.ParseExpression(this, _instance) + @");
                                        if (!System.Text.RegularExpressions.Regex.IsMatch(instanceIDTemp, ""^\\d+$""))
                                            instanceID = (int)Manager.Instances.Select(AliCMS.SystemModule.Alias.Instance.ID + ""='"" + instanceIDTemp + ""'"")[0][AliCMS.SystemModule.Alias.Instance.InnerID];
                                        else
                                            instanceID = Convert.ToInt32(instanceIDTemp);";
                    }
                }
            }
            #endregion

            #region RecordCount
            if (_operation == null && _source == null)
            {
                result.Append(@"
                        protected int <%ID%>RecordCount
                        {
                            get
                            {
                                <%InstanceID%>
                                using (<%Namespace%>.<%Interface%> bll = (<%Namespace%>.<%Interface%>)Manager.CreateObject(""<%Object%>"", instanceID, <%Lang%>, <%Validate%>))
                                {
                                    <%Condition%>

                                    return bll." + _operationName.Replace("List", "Get") + @"RecordCount(condition);
                                }
                            }
                        }
                        ");
            }
            #endregion

            #region Page
            string page = "-1";
            re = new Regex("Page=\"(?<v>.*?)\"", RegexOptions.Compiled);
            if (_record == null)
                match = re.Match(Engine.Text, Index, Length);
            else
                match = re.Match(Engine.Text, Index, ContentIndex - Index);
            if (match.Success)
            {
                page = match.Groups["v"].Value;
                if (!Regex.IsMatch(page, @"^\d+$"))
                    page = "Convert.ToInt32(" + Engine.ParseExpression(this, page) + ")";
            }
            #endregion

            #region PageSize
            string pageSize = "-1";
            re = new Regex("PageSize=\"(?<v>.*?)\"", RegexOptions.Compiled);
            if (_record == null)
                match = re.Match(Engine.Text, Index, Length);
            else
                match = re.Match(Engine.Text, Index, ContentIndex - Index);
            if (match.Success)
            {
                pageSize = match.Groups["v"].Value;
                if (!Regex.IsMatch(pageSize, @"^\d+$"))
                    pageSize = "Convert.ToInt32(" + Engine.ParseExpression(this, pageSize) + ")";
            }
            #endregion

            #region Condition
            StringBuilder condition = ParseCondition();
            #endregion

            #region Sort
            StringBuilder sort = new StringBuilder();
            sort.Append("string sort = null;");
            re = new Regex("Sort=\"(?<v>.*?)\"", RegexOptions.Compiled);
            if (_record == null)
                match = re.Match(Engine.Text, Index, Length);
            else
                match = re.Match(Engine.Text, Index, ContentIndex - Index);
            if (match.Success)
            {
                DataRow[] properties = Manager.Properties.Select(Alias.Module.Object.Property.ObjectID + "='" + _object[Alias.Module.Object.ID] + "'");

                bool find = false;
                StringBuilder value = new StringBuilder();
                string[] items = match.Groups["v"].Value.Split(',');
                foreach (string item in items)
                {
                    find = false;
                    string[] pair = item.Trim().Split(' ');
                    foreach (DataRow property in properties)
                    {
                        string alias = property[Alias.Module.Object.Property.UniqueInnerID].ToString();
                        string name = property[Alias.Module.Object.Property.Name].ToString();
                        if (name == pair[0])
                        {
                            if (value.Length != 0)
                                value.Append(",");
                            
                            if (pair.Length > 1)
                                value.Append(alias + " " + pair[1]);
                            else
                                value.Append(alias);

                            find = true;
                            break;
                        }
                    }

                    if (!find)
                        break;
                }

                if (find)
                    sort.Append("sort = \"" + value + "\";");
                else
                    sort.Append("sort = " + Engine.ParseExpression(this, match.Groups["v"].Value) + ";");
            }
            #endregion

            #region RowSeparator
            StringBuilder rowSeparatorReplacement = new StringBuilder();
            if (_row != null)
            {
                foreach (Tag tag in _row.ChildTags)
                {
                    if (tag is Separator)
                    {
                        foreach (Tag separatorChildTag in tag.ChildTags)
                        {
                            if (separatorChildTag is Code)
                            {
                                rowSeparatorReplacement.Append(separatorChildTag.ResultCode);
                            }
                            else if (tag is OutputStatment)
                            {
                                result.Append("object " + tag.UniqueName + " = " + tag.ResultCode + ";\r\n");
                                result.Append(UniqueName + " = " + UniqueName + ".Replace(\"{#" + tag.UniqueName + "#}\"," + tag.UniqueName + " == null ? \"\" : " + tag.UniqueName + ".ToString());\r\n");
                            }
                            else if (separatorChildTag is IfStatment)
                            {
                                rowSeparatorReplacement.Append(separatorChildTag.ResultCode);
                                rowSeparatorReplacement.Append("rowSeparator = rowSeparator.Replace(\"{#" + separatorChildTag.UniqueName + "#}\"," + separatorChildTag.UniqueName + ");\r\n");
                            }
                            else if (separatorChildTag.ResultCode != null && Regex.IsMatch(separatorChildTag.ResultCode, "protected string " + separatorChildTag.UniqueName + @"\s+{\s+get\s+"))
                            {
                                rowSeparatorReplacement.Append("rowSeparator = rowSeparator.Replace(\"{#" + separatorChildTag.UniqueName + "#}\"," + separatorChildTag.UniqueName + ");\r\n");
                            }
                        }
                    }
                }
            }
            #endregion

            #region ColSeparator
            StringBuilder colSeparatorReplacement = new StringBuilder();
            if (_col != null)
            {
                foreach (Tag tag in _row.ChildTags)
                {
                    if (tag is Separator)
                    {
                        foreach (Tag separatorChildTag in tag.ChildTags)
                        {
                            if (separatorChildTag is Code)
                            {
                                colSeparatorReplacement.Append(separatorChildTag.ResultCode);
                            }
                            else if (tag is OutputStatment)
                            {
                                result.Append("object " + tag.UniqueName + " = " + tag.ResultCode + ";\r\n");
                                result.Append(UniqueName + " = " + UniqueName + ".Replace(\"{#" + tag.UniqueName + "#}\"," + tag.UniqueName + " == null ? \"\" : " + tag.UniqueName + ".ToString());\r\n");
                            }
                            else if (separatorChildTag is IfStatment)
                            {
                                colSeparatorReplacement.Append(separatorChildTag.ResultCode);
                                colSeparatorReplacement.Append("colSeparator = colSeparator.Replace(\"{#" + separatorChildTag.UniqueName + "#}\"," + separatorChildTag.UniqueName + ");\r\n");
                            }
                            else if (separatorChildTag.ResultCode != null && Regex.IsMatch(separatorChildTag.ResultCode, "protected string " + separatorChildTag.UniqueName + @"\s+{\s+get\s+"))
                            {
                                colSeparatorReplacement.Append("colSeparator = colSeparator.Replace(\"{#" + separatorChildTag.UniqueName + "#}\"," + separatorChildTag.UniqueName + ");\r\n");
                            }
                        }
                    }
                }
            }
            #endregion

            #region RecordReplacement
            StringBuilder recordReplacement = new StringBuilder();
            if (_record != null)
            {
                MakeRecordReplacementCode(_record);

                recordReplacement.Append(_complex);
                recordReplacement.Append(_statment);
                recordReplacement.Append(_aliasStatment);
            }
            #endregion

            #region AllReplacement
            StringBuilder allReplacement = new StringBuilder();
            foreach (Tag tag in ChildTags)
            {
                if (tag is Row || tag is Col || tag is Record)
                    continue;

                if (tag is Code)
                {
                    allReplacement.Append(tag.ResultCode);
                }
                else if (tag is OutputStatment)
                {
                    allReplacement.Append("object " + tag.UniqueName + " = " + tag.ResultCode + ";\r\n");
                    allReplacement.Append("all.Replace(\"{#" + tag.UniqueName + "#}\"," + tag.UniqueName + " == null ? \"\" : " + tag.UniqueName + ".ToString());\r\n");
                }
                else if (tag is IfStatment)
                {
                    allReplacement.Append(tag.ResultCode);
                    allReplacement.Append("all.Replace(\"{#" + tag.UniqueName + "#}\"," + tag.UniqueName + ");\r\n");
                }
                else if (tag.ResultCode != null && Regex.IsMatch(tag.ResultCode, "protected string " + tag.UniqueName + @"\s+{\s+get\s+"))
                {
                    allReplacement.Append("all.Replace(\"{#" + tag.UniqueName + "#}\"," + tag.UniqueName + ");\r\n");
                }
            }
            #endregion

            result.Append(@"
                            protected int <%ID%>Counter = 0;
                            protected object <%ID%>Record = null;
                            private DataTable <%ID%>Data;
                            protected DataTable <%ID%>
                            {
                                get
                                {
                                    if (<%ID%>Data != null)
                                        return <%ID%>Data;

                                    <%ID%>Data = <%ID%>_;
                                    return <%ID%>Data;
                                }
                            }
                        ");

            if (_source == null)
            {
                result.Append(@"
                                private DataTable <%ID%>_
                                {
                                    get
                                    {
                                        <%Condition%>

                                        <%Sort%>

                                        <%InstanceID%>

                                        using (<%Namespace%>.<%Interface%> bll = (<%Namespace%>.<%Interface%>)Manager.CreateObject(""<%Object%>"", instanceID, <%Lang%>, <%Validate%>))
                                        {
                                            <%ID%>Data = bll.<%Operation%>;
                                        }

                                        return <%ID%>Data;
                                    }
                                }
                            ");

                if (_record == null)
                {
                    result.Append(@"
                            protected string <%Name%>
                            {
                                get
                                {
                                    <%ID%>Data = <%ID%>_;

                                    XmlNode node = _xmlTemplate.SelectSingleNode(""//<%Name%>"");
                                    StringBuilder all = new StringBuilder();
                                    all.Replace(""{#Row#}"", """");
                                    <%AllReplacement%>

                                    return all.ToString();
                                }
                            }
                                ");
                }
                else
                {
                    result.Append(@"
                            protected string <%Name%>
                            {
                                get
                                {
                                    XmlNode node = _xmlTemplate.SelectSingleNode(""//<%Name%>"");
                                    Dictionary<string, object> replacementPair = new Dictionary<string, object>();
                                    <%RecordReplacement%>
                                    StringBuilder all = Manager.Build(node, <%ID%>_, replacementPair, ref <%ID%>Record, ref <%ID%>Counter);
                                    <%RowSeparatorReplacement%>
                                    <%ColSeparatorReplacement%>
                                    <%AllReplacement%>
                                    return all.ToString();
                                }
                            }
                          ");
                }
                if (_operation == null)
                {
                    result.Replace("<%Condition%>", condition.ToString());
                    result.Replace("<%Sort%>", sort.ToString());
                    result.Replace("<%Operation%>", _operationName + "(" + page + ", " + pageSize + ", condition, sort)");
                }
                else
                {
                    result.Replace("<%Condition%>", "");
                    result.Replace("<%Sort%>", "");
                    result.Replace("<%Operation%>", _operation.Parse());
                }
                result.Replace("<%Namespace%>", _module[Alias.Module.Namespace].ToString());
                result.Replace("<%Interface%>", _interfaceName);
                result.Replace("<%Object%>", _object["FullName"].ToString());
                result.Replace("<%InstanceID%>", instanceID);
                result.Replace("<%Validate%>", Validate);
            }
            else
            {
                result.Append(@"
                        protected DataTable <%ID%>_
                        {
                            get
                            {
                                <%Condition%>
                                if (!String.IsNullOrEmpty(condition))
                                {
                                    DataTable temp = <%Source%>;
                                    <%ID%>Data = temp.Clone();
                                    DataRow[] rows = temp.Select(condition);
                                    foreach (DataRow row in rows)
                                        <%ID%>Data.ImportRow(row);
                                }
                                else
                                {
                                    <%ID%>Data = <%Source%>;
                                }
                                return <%ID%>Data;
                            }
                        }
                        protected string <%Name%>
                        {
                            get
                            {
                                XmlNode node = _xmlTemplate.SelectSingleNode(""//<%Name%>"");
                                Dictionary<string, object> replacementPair = new Dictionary<string, object>();
                                <%RecordReplacement%>
                                StringBuilder all = Manager.Build(node, <%ID%>_, replacementPair, ref <%ID%>Record, ref <%ID%>Counter);
                                <%RowSeparatorReplacement%>
                                <%ColSeparatorReplacement%>
                                <%AllReplacement%>
                                return all.ToString();
                            }
                        }
                      ");
                result.Replace("<%Source%>", _source.Parse());
                result.Replace("<%Condition%>", condition.ToString());
            }

            result.Replace("<%RowSeparatorReplacement%>", rowSeparatorReplacement.ToString());
            result.Replace("<%ColSeparatorReplacement%>", colSeparatorReplacement.ToString());
            result.Replace("<%RecordReplacement%>", recordReplacement.ToString());
            result.Replace("<%AllReplacement%>", allReplacement.ToString());
            result.Replace("<%ID%>", _id);
            result.Replace("<%Name%>", UniqueName);
            if (String.IsNullOrEmpty(_lang))
            {
                if (Engine.IsAdmin)
                    result.Replace("<%Lang%>", "ContentLang");
                else
                    result.Replace("<%Lang%>", "PageLang");
            }
            else
            {
                result.Replace("<%Lang%>", Engine.ParseExpression(this, _lang));
            }

            ResultCode = result.ToString();
        }
        private void ParseToXml()
        {
            if (ChildTags.Count == 0)
                return;

            #region Record和RecordSeparator
            _recordSeparatorXml = new StringBuilder();
            StringBuilder record = new StringBuilder();
            if (_record != null)
            {
                record.Append(Engine.Text.Substring(_record.ContentIndex, _record.ContentLength));
                MakeRecordReplacementXml(_record, record);
                record.Append("{#Record#}");
            }
            #endregion

            #region Col，ColSeparator，MaxRecord
            StringBuilder col = new StringBuilder();
            StringBuilder colSeparator = new StringBuilder();
            string maxRecord = "0";
            if (_col == null)
            {
                col.Append("{#Record#}");
            }
            else
            {
                Regex re = new Regex("MaxRecord=\"(?<v>.*?)\"", RegexOptions.Compiled);
                Match match = re.Match(Engine.Text, _col.Index, _col.ContentIndex - _col.Index);
                if (match.Success)
                    maxRecord = match.Groups["v"].Value;

                col.Append(Engine.Text.Substring(_col.ContentIndex, _col.ContentLength));
                for (int i = _col.ChildTags.Count - 1; i >= 0; i--)
                {
                    Tag tag = _col.ChildTags[i];
                    col.Remove(tag.Index - _col.ContentIndex, tag.Length);
                    if (tag is Separator)
                    {
                        colSeparator.Append(Engine.Text.Substring(tag.ContentIndex, tag.ContentLength));
                        for (int j = tag.ChildTags.Count - 1; j >= 0; j--)
                        {
                            Tag separatorChild = tag.ChildTags[j];
                            colSeparator.Remove(separatorChild.Index - tag.ContentIndex, separatorChild.Length);
                            if (separatorChild is IfStatment || tag is OutputStatment || (separatorChild.ResultCode != null && Regex.IsMatch(separatorChild.ResultCode, "protected string " + separatorChild.UniqueName + @"\s+{\s+get\s+")))
                                colSeparator.Insert(separatorChild.Index - tag.ContentIndex, "{#" + separatorChild.UniqueName + "#}");
                        }

                    }
                    else if (tag is Record)
                    {
                        col.Insert(tag.Index - _col.ContentIndex, "{#Record#}");
                    }
                }
            }
            col.Append("{#Col#}");
            #endregion

            #region Row，RowSeparator，MaxCol
            StringBuilder row = new StringBuilder();
            StringBuilder rowSeparator = new StringBuilder();
            string maxCol = "0";
            if (_row == null)
            {
                row.Append("{#Col#}");
            }
            else
            {
                Regex re = new Regex("MaxCol=\"(?<v>.*?)\"", RegexOptions.Compiled);
                Match match = re.Match(Engine.Text, _row.Index, _row.ContentIndex - _row.Index);
                if (match.Success)
                    maxCol = match.Groups["v"].Value;

                row.Append(Engine.Text.Substring(_row.ContentIndex, _row.ContentLength));
                for (int i = _row.ChildTags.Count - 1; i >= 0; i--)
                {
                    Tag tag = _row.ChildTags[i];
                    row.Remove(tag.Index - _row.ContentIndex, tag.Length);
                    if (tag is Separator)
                    {
                        rowSeparator.Append(Engine.Text.Substring(tag.ContentIndex, tag.ContentLength));
                        for (int j = tag.ChildTags.Count - 1; j >= 0; j--)
                        {
                            Tag separatorChild = tag.ChildTags[j];
                            rowSeparator.Remove(separatorChild.Index - tag.ContentIndex, separatorChild.Length);
                            if (separatorChild is IfStatment || tag is OutputStatment || (separatorChild.ResultCode != null && Regex.IsMatch(separatorChild.ResultCode, "protected string " + separatorChild.UniqueName + @"\s+{\s+get\s+")))
                                rowSeparator.Insert(separatorChild.Index - tag.ContentIndex, "{#" + separatorChild.UniqueName + "#}");
                        }

                    }
                    else if (tag is Col || tag is Record)
                    {
                        row.Insert(tag.Index - _row.ContentIndex, "{#Col#}");
                    }
                }
            }
            row.Append("{#Row#}");
            #endregion

            #region All
            StringBuilder all = new StringBuilder(Engine.Text.Substring(ContentIndex, ContentLength));
            for (int i = ChildTags.Count - 1; i >= 0; i--)
            {
                Tag tag = ChildTags[i];
                all.Remove(tag.Index - ContentIndex, tag.Length);
                if (tag is Row || tag is Col || tag is Record)
                    all.Insert(tag.Index - ContentIndex, "{#Row#}");
                else if (tag is IfStatment || tag is OutputStatment || (tag.ResultCode != null && Regex.IsMatch(tag.ResultCode, "protected string " + tag.UniqueName + @"\s+{\s+get\s+")))
                    all.Insert(tag.Index - ContentIndex, "{#" + tag.UniqueName + "#}");
            }
            #endregion

            #region 生成Xml
            StringBuilder result = new StringBuilder();
            result.Append(@"
		                <RowSeparator>
			                <![CDATA[<%RowSeparator%>]]>
		                </RowSeparator>
		                <ColSeparator>
			                <![CDATA[<%ColSeparator%>]]>
		                </ColSeparator>
		                <RecordSeparator>
			                <![CDATA[<%RecordSeparator%>]]>
		                </RecordSeparator>
		                <Record>
			                <![CDATA[<%Record%>]]>
		                </Record>
		                <Col MaxRecord=""<%MaxRecord%>"">
			                <![CDATA[<%Col%>]]>
		                </Col>
		                <Row MaxCol=""<%MaxCol%>"">
			                <![CDATA[<%Row%>]]>
		                </Row>
		                <All>
			                <![CDATA[<%All%>]]>
		                </All>
                        ");
            result.Replace("<%RowSeparator%>", rowSeparator.ToString());
            result.Replace("<%ColSeparator%>", colSeparator.ToString());
            result.Replace("<%RecordSeparator%>", _recordSeparatorXml.ToString());
            result.Replace("<%Record%>", record.ToString());
            result.Replace("<%Col%>", col.ToString());
            result.Replace("<%Row%>", row.ToString());
            result.Replace("<%MaxRecord%>", maxRecord);
            result.Replace("<%MaxCol%>", maxCol);
            result.Replace("<%All%>", all.ToString());
            ResultXml = result.ToString();
            #endregion
        }
        private void MakeRecordReplacementCode(Tag tag)
        {
            foreach (Tag childTag in tag.ChildTags)
            {
                if (childTag is Code || (!(childTag is Separator) && childTag.ResultCode == null))
                    continue;

                if (childTag is OutputStatment)
                {
                    string content = Engine.Text.Substring(childTag.ContentIndex, childTag.ContentLength).Replace("\"", "\"\"");
                    if (_repeatCheckList.Contains(content))
                        continue;

                    _statment.Append(@"
                                        replacementPair[@""{#" + content + @"#}""] = new CustomBuild(
                                                                        delegate(DataRow record, int index)
                                                                        {
                                                                            object " + childTag.UniqueName + " = " + childTag.ResultCode + @";
                                                                            if (" + childTag.UniqueName + @" != null)
                                                                                return " + childTag.UniqueName + @".ToString();
                                                                            else
                                                                                return String.Empty;
                                                                        }
                                                                        );
                                                ");
                    _repeatCheckList.Add(content);
                }
                else if (childTag is IfStatment)
                {
                    _complex.Append(@"
                                        replacementPair[""{#" + childTag.UniqueName + @"#}""] = new CustomBuild(
                                                                        delegate(DataRow record, int index)
                                                                        {"
                                                                        + childTag.ResultCode +
                                                                    @"
                                                                            return " + childTag.UniqueName + @";
                                                                        }
                                                                        );
                                                ");
                }
                else if (childTag.ResultCode != null && Regex.IsMatch(childTag.ResultCode, "protected string " + childTag.UniqueName + @"\s+{\s+get\s+"))
                {
                    _complex.Append(@"
                                        replacementPair[""{#" + childTag.UniqueName + @"#}""] = new CustomBuild(
                                                                        delegate(DataRow record, int index)
                                                                        { return " + childTag.UniqueName + @";}
                                                                        );
                                                ");
                }
                else if (childTag is Separator)
                {
                    MakeRecordReplacementCode(childTag);
                }
            }
        }
        private void MakeRecordReplacementXml(Tag tag, StringBuilder result)
        {
            for (int i = tag.ChildTags.Count - 1; i >= 0; i--)
            {
                Tag childTag = tag.ChildTags[i];
                result.Remove(childTag.Index - tag.ContentIndex, childTag.Length);

                if (childTag is OutputStatment)
                {
                    string content = Engine.Text.Substring(childTag.ContentIndex, childTag.ContentLength);
                    result.Insert(childTag.Index - tag.ContentIndex, "{#" + content + "#}");
                }
                else if (childTag is IfStatment || (childTag.ResultCode != null && Regex.IsMatch(childTag.ResultCode, "protected string " + childTag.UniqueName + @"\s+{\s+get\s+")))
                {
                    result.Insert(childTag.Index - tag.ContentIndex, "{#" + childTag.UniqueName + "#}");
                }
                else if (childTag is Separator)
                {
                    _recordSeparatorXml.Append(Engine.Text.Substring(childTag.ContentIndex, childTag.ContentLength));
                    MakeRecordReplacementXml(childTag, _recordSeparatorXml);
                }
            }
        }

        #region Fields
        private Tag _record;
        private Tag _col;
        private Tag _row;
        private string _id;
        private string _mark;
        private string _instance;
        private string _interfaceName;
        private string _lang;
        private string _operationName;
        private Expression _operation;
        private Expression _source;
        private Type _returnType;
        private ParameterInfo[] _pi;
        private DataRow _module;
        private DataRow _object;
        private StringBuilder _recordSeparatorXml;
        private StringBuilder _aliasStatment;
        private StringBuilder _statment;
        private StringBuilder _complex;
        private List<string> _repeatCheckList;
        #endregion
    }
}
